package
{
	import com.demonsters.debugger.MonsterDebugger;
	import com.zero.zsingleton.ComponentSingleton;
	import com.zero.zsingleton.LanguageSingleton;
	import com.zero.zui.ExtendTextField;
	import com.zero.zutils.UiUtils;
	
	import flash.display.Bitmap;
	import flash.display.ColorCorrection;
	import flash.display.Shape;
	import flash.display.SimpleButton;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.TimerEvent;
	import flash.geom.Point;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.text.TextColorType;
	import flash.text.TextField;
	import flash.text.TextFormat;
	import flash.ui.Keyboard;
	import flash.utils.Dictionary;
	import flash.utils.Timer;
	
	import mx.core.mx_internal;
	
	import org.osmf.events.TimeEvent;
	
	import yzhkof.debug.DebugSystem;
	
	public class Tetris extends Sprite
	{
		private var _backgroundShape		:Shape;
		private var _backTileShape			:Shape;
		private var _currentTileShape		:Shape;
		private var _previewShape			:Shape;
		private var _gameBorderShape		:Shape;
		private var _gameMaskShape			:Shape;
										
		private var _timer					:Timer;
		
		private var _tempTile				:Tile;
		private var _tempX					:int;
		private var _tempY					:int;
		private var _backNumX				:int;
		private var _backNumY				:int;
		private var _gameOver				:Boolean;
		private var _gameStop				:Boolean;
		
		private var _gameMaskTextField		:ExtendTextField;
		
		public var gameScore				:int;
		public var gameLevel				:int;
				
		public function Tetris()
		{
			initData();
			initView();
		}
		
		private function addEvent():void
		{
			_timer.addEventListener(TimerEvent.TIMER_COMPLETE, __timeCompleteHandler);
			
		}
		
		private function removeEvent():void
		{
			_timer.removeEventListener(TimerEvent.TIMER_COMPLETE, __timeCompleteHandler);
		}
		
		private function __timeCompleteHandler(e:TimerEvent):void
		{
			_timer.reset();
			if(checkGameOver())
			{
				overGame();
				return;
			}
			else if(_tempTile.checkDown())
			{
				updateCurrentTileData(_tempTile.tempX, _tempTile.tempY, TileUtils.BACK_TILE);
				_tempTile.tempY ++;
				updateCurrentTileData(_tempTile.tempX, _tempTile.tempY, TileUtils.CURRENT_TILE);
			}
			else
			{
				updateCurrentTileData(_tempTile.tempX, _tempTile.tempY, TileUtils.FIXED_TILE);
				resetTile();
			}
			checkDispel();
			_timer.start();
		}
		
		public function tileStateChange($keyCode:uint):void
		{
			switch($keyCode)
			{
				case Keyboard.UP:
					if(_tempTile.checkTransform())
					{
						_tempTile.direction = _tempTile.direction+1>3 ? 0 : _tempTile.direction+1;
						updateCurrentTileData(_tempTile.tempX, _tempTile.tempY, TileUtils.BACK_TILE);
						_tempTile.tileArr = TileUtils.computeTileData(_tempTile.type, _tempTile.direction);
						updateCurrentTileData(_tempTile.tempX, _tempTile.tempY, TileUtils.CURRENT_TILE);
					}
					break;
					break;
				case Keyboard.DOWN:
					if(_tempTile.checkDown())
					{
						updateCurrentTileData(_tempTile.tempX, _tempTile.tempY, TileUtils.BACK_TILE);
						_tempTile.tempY ++;
						updateCurrentTileData(_tempTile.tempX, _tempTile.tempY, TileUtils.CURRENT_TILE);
					}
					break;
				case Keyboard.LEFT:
					if(_tempTile.checkLeft())
					{
						updateCurrentTileData(_tempTile.tempX, _tempTile.tempY, TileUtils.BACK_TILE);
						_tempTile.tempX --;
						updateCurrentTileData(_tempTile.tempX, _tempTile.tempY, TileUtils.CURRENT_TILE);
					}
					break;
				case Keyboard.RIGHT:
					if(_tempTile.checkRight())
					{
						updateCurrentTileData(_tempTile.tempX, _tempTile.tempY, TileUtils.BACK_TILE);
						_tempTile.tempX ++;
						updateCurrentTileData(_tempTile.tempX, _tempTile.tempY, TileUtils.CURRENT_TILE);
					}
					break;
				default:
					break;
			}
		}
		
		private function initData():void
		{
			gameScore = 0;
			_gameOver = false;
			_gameStop = false;
			_timer = new Timer(TileUtils.TIME_COUNT, 1);
			addEvent();
			_timer.start();
			initTileData();
		}
		
		private function initView():void
		{
			_backTileShape = new Shape();
			_currentTileShape = new Shape();
			
			initBackground();
			initPreview();
//			initGameBorder();
			resetTile();
			updateCurrentTileData(_tempTile.tempX, _tempTile.tempY,TileUtils.CURRENT_TILE);
			updateTileShape();
		}
		
		private function initGameBorder():void
		{
			_gameBorderShape = new Shape();
			_gameBorderShape = TileUtils.drawShape(_gameBorderShape, 0, 0, TileUtils.GAME_COLOR, TileUtils.GAME_BORDER_COLOR, TileUtils.TILE_X_NUM*TileUtils.TILE_WIDTH, TileUtils.TILE_Y_NUM*TileUtils.TILE_HEIGHT, 0);
			addChild(_gameBorderShape);
		}
		
		private function initTileData():void
		{
			for(var i:int=0; i < TileUtils.TILE_X_NUM; i ++)
			{
				model.tileArr[i] = [];
				for(var j:int=0; j < TileUtils.TILE_Y_NUM; j ++)
				{
					model.tileArr[i][j] = TileUtils.BACK_TILE;
				}
			}
		}
		
		private function initBackground():void
		{
			_backgroundShape = new Shape();
			for(var i:int=0; i < TileUtils.TILE_X_NUM; i ++)
			{
				for(var j:int=0; j < TileUtils.TILE_Y_NUM; j ++)
				{
					_backgroundShape = TileUtils.drawShape(_backgroundShape, i*TileUtils.TILE_WIDTH, j*TileUtils.TILE_HEIGHT, TileUtils.BG_COLOR, TileUtils.BORDER_COLOR);
				}
			}
			_backgroundShape.x = TileUtils.BACKGROUND_X;
			_backgroundShape.y = TileUtils.BACKGROUND_Y;
			addChild(_backgroundShape);
		}
		
		private function initPreview():void
		{
			_previewShape = new Shape();
			for(var i:int=0; i < TileUtils.PREVIEW_X_NUM; i ++)
			{
				for(var j:int=0; j < TileUtils.PREVIEW_Y_NUM; j ++)
				{
					_previewShape = TileUtils.drawShape(_previewShape, i*TileUtils.TILE_WIDTH, j*TileUtils.TILE_HEIGHT, TileUtils.PREVIEW_COLOR, TileUtils.BORDER_COLOR);
				}
			}
			_previewShape.x = TileUtils.PREVIEW_X;
			_previewShape.y = TileUtils.PREVIEW_Y;
			addChild(_previewShape);
		}
		
		public function updateTileShape():void
		{
			if(_gameStop || _gameOver)
			{
				return;
			}
			UiUtils.removeFromDisplay(_backTileShape);
			UiUtils.removeFromDisplay(_currentTileShape);
			
			_backTileShape.graphics.clear();
			_currentTileShape.graphics.clear();
			
			for(var i:int=0; i < TileUtils.TILE_X_NUM; i ++)
			{
				for(var j:int=0; j < TileUtils.TILE_Y_NUM; j ++)
				{
					if(model.tileArr[i][j] == TileUtils.FIXED_TILE)
					{
						_backTileShape = TileUtils.drawShape(_backTileShape, i*TileUtils.TILE_WIDTH, j*TileUtils.TILE_HEIGHT, TileUtils.TILE_COLOR, TileUtils.BORDER_COLOR);
					}
					if(model.tileArr[i][j] == TileUtils.CURRENT_TILE)
					{
						_currentTileShape = TileUtils.drawShape(_currentTileShape, i*TileUtils.TILE_WIDTH, j*TileUtils.TILE_HEIGHT, TileUtils.TILE_COLOR, TileUtils.BORDER_COLOR);
					}
				}
			}
			UiUtils.addToDisplay(_backTileShape, this);
			UiUtils.addToDisplay(_currentTileShape, this);
		}
		
		private function resetTile():void
		{
			if(!_tempTile)_tempTile = new Tile();
			_tempTile.type = int(Math.random()*6);
			_tempTile.direction = int(Math.random()*3);
			_tempTile.tempX = TileUtils.NEW_TILE_X;
			_tempTile.tempY = TileUtils.NEW_TILE_Y;
			_tempTile.tileArr = TileUtils.computeTileData(_tempTile.type, _tempTile.direction);
		}
		
		private function checkDispel():void
		{
			var floorRow:int = 0;
			for(var i:int=TileUtils.TILE_Y_NUM-1; i >= 0; i --)
			{
				var floorNum:int = 0;
				for(var j:int=TileUtils.TILE_X_NUM-1; j >= 0; j --)
				{
					if(model.tileArr[j][i] == TileUtils.FIXED_TILE)
					{
						floorNum ++;
					}
				}
				if(floorNum >= TileUtils.TILE_X_NUM)
				{
					floorRow ++;
					for(var k:int=TileUtils.TILE_X_NUM-1; k >= 0; k --)
					{
						model.tileArr[k][i] = TileUtils.BACK_TILE;
					}
					for(var m:int=i; m >= 0; m --)
					{
						for(var n:int=TileUtils.TILE_X_NUM-1; n >= 0; n --)
						{
							if(model.tileArr[n][m-1] == TileUtils.FIXED_TILE)
							{
								model.tileArr[n][m] = TileUtils.FIXED_TILE;
								model.tileArr[n][m-1] = TileUtils.BACK_TILE;
							}
						}
					}
					i ++;
					gameScore += floorRow*2 - 1;
					gameLevel = gameScore/10;
					if(_timer.delay > 100)
					{
						_timer.delay = TileUtils.TIME_COUNT - gameLevel*100;
					}
				}
			}
			updateTileShape();
		}
		
		private function checkGameOver():Boolean
		{
			for(var i:int=0; i < TileUtils.PREVIEW_X_NUM; i ++)
			{
				for(var j:int=0; j < TileUtils.PREVIEW_Y_NUM; j ++)
				{
					if(model.tileArr[i][j] == TileUtils.FIXED_TILE)
					{
						return true;
					}
				}
			}
			return false;
		}
		
		private function showMaskText($text:String):void
		{
			if(!_gameMaskTextField)
			{
				_gameMaskTextField 		= ComponentSingleton.instance.createComponentByStylename("tetris.gameMaskTxt");
				_gameMaskTextField.x 	= TileUtils.STAGE_WIDTH/2 - _gameMaskTextField.width/2;
				_gameMaskTextField.y 	= TileUtils.STAGE_HEIGHT/2 - _gameMaskTextField.height/2;
				_gameMaskShape 			= TileUtils.createMask(TileUtils.STAGE_WIDTH, TileUtils.STAGE_HEIGHT);
			}
			_gameMaskTextField.text = $text;
			UiUtils.addToDisplay(_gameMaskShape, this);
			UiUtils.addToDisplay(_gameMaskTextField, this);
		}
		
		private function hideMaskText():void
		{
			UiUtils.removeFromDisplay(_gameMaskShape);
			UiUtils.removeFromDisplay(_gameMaskTextField);
		}
		
		private function updateCurrentTileData($tempX:int, $tempY:int, $state:int):void
		{
			for(var i:int=0; i < _tempTile.tileArr.length; i ++)
			{
				_tempX = $tempX + _tempTile.tileArr[i][0];
				_tempY = $tempY + _tempTile.tileArr[i][1];
				model.tileArr[_tempX][_tempY] = $state;
			}
		}
		
		public function resetGame():void
		{
			hideMaskText();
			initData();
			_backTileShape.graphics.clear();
			_currentTileShape.graphics.clear();
			resetTile();
			updateCurrentTileData(_tempTile.tempX, _tempTile.tempY,TileUtils.CURRENT_TILE);
			updateTileShape();
		}
		
		public function stopGame():void
		{
			if(!_gameStop && !_gameOver)
			{
				_timer.stop();
				_gameStop = true;
				removeEvent();
				showMaskText(LanguageSingleton.instance.GetTranslation("Tetris.gameStopTextField.text"));
			}
		}
		
		public function resumeGame():void
		{
			if(_gameStop && !_gameOver)
			{
				_timer.start();
				_gameStop = false;
				addEvent();
				hideMaskText();
			}
		}
		
		public function overGame():void
		{
			if(!_gameOver)
			{
				_timer.stop();
				_gameOver = true;
				removeEvent();
				showMaskText(LanguageSingleton.instance.GetTranslation("Tetris.gameOverTextField.text"));
			}
		}
		
		private function get model():TileModel
		{
			return TileManager.instance.model;
		}
		
		private function unint():void
		{
			UiUtils.disposeAllChildren(this);
		}
		
		public function dispose():void
		{
			removeEvent();
			unint();
		}
		
		
	}
}